package com.own.component.elastic.service;

import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregation;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.util.ObjectBuilder;
import com.own.component.common.base.entity.po.BaseBean;
import com.own.component.common.model.PageModel;
import com.own.component.elastic.constant.ElasticSearchCommonConstant;
import com.own.component.elastic.entity.BaseElasticPo;
import com.own.component.elastic.entity.BaseElasticQuery;
import com.own.component.elastic.entity.BaseElasticVo;
import com.own.component.elastic.service.config.ElasticSearchConfig;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;

/**
 * BaseElasticSearchService
 *
 * @author chenxueli
 * @date 2022-09-03 19:16:00
 */
public interface BaseElasticSearchService<
        PO extends BaseBean,
        ELASTIC_PO extends BaseElasticPo<PO>,
        ELASTIC_VO extends BaseElasticVo<ELASTIC_PO>,
        QUERY extends BaseElasticQuery
        > {

    /**
     * 根据id获取信息
     *
     * @param id 主键id
     * @return 对象信息
     */
    ELASTIC_PO getPoById(String id);

    /**
     * 根据id获取信息
     *
     * @param id 主键id
     * @return 对象信息
     */
    ELASTIC_VO getById(String id);

    /**
     * 根据id获取信息
     *
     * @param idList 主键ids
     * @return 对象信息列表
     */
    List<ELASTIC_PO> listPoByIdList(Collection<String> idList);

    /**
     * 根据id获取信息
     *
     * @param idList 主键ids
     * @return 对象信息列表
     */
    List<ELASTIC_VO> listByIdList(Collection<String> idList);

    /**
     * 根据id获取信息
     *
     * @param idList   主键ids
     * @param function 转换函数
     * @return 对象信息列表
     */
    List<ELASTIC_VO> listByIdList(Collection<String> idList, Function<Hit<ELASTIC_PO>, ELASTIC_VO> function);

    /**
     * 分页搜索
     *
     * @param query 查询条件
     * @return 分页结果
     */
    default PageModel<ELASTIC_VO> page(QUERY query) {
        return page(query, getDefaultConfig());
    }

    /**
     * 分页搜索
     *
     * @param query 查询条件
     * @param cache 是否使用缓存
     * @return 分页结果
     */
    default PageModel<ELASTIC_VO> page(QUERY query, boolean cache) {
        return page(query, getDefaultConfig(), cache);
    }

    /**
     * 分页搜索
     * 参数构造参考https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html
     *
     * @param query        查询条件
     * @param queryBuilder 查询条件构造器
     * @return 分页结果
     */
    default PageModel<ELASTIC_VO> page(
            QUERY query,
            Function<Query.Builder, ObjectBuilder<Query>> queryBuilder
    ) {
        var config = ElasticSearchConfig.<PO, ELASTIC_PO, ELASTIC_VO, QUERY>builder().queryBuilder((temp, c) -> queryBuilder).build();
        return page(query, config, null);
    }

    /**
     * 分页搜索
     *
     * @param query  查询条件
     * @param config 查询配置信息
     * @return 分页结果
     */
    default PageModel<ELASTIC_VO> page(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config
    ) {
        return page(query, config, null);
    }

    /**
     * 分页搜索
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param filterConsumer 自定义的筛选条件内容
     * @return 分页结果
     */
    PageModel<ELASTIC_VO> page(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Consumer<BoolQuery.Builder> filterConsumer
    );

    /**
     * 聚合查询
     *
     * @param query       查询条件
     * @param aggregation 聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(QUERY query, Aggregation aggregation) {
        return aggregation(query, getDefaultConfig(), null, aggregation);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregation    聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(QUERY query, Consumer<BoolQuery.Builder> filterConsumer, Aggregation aggregation) {
        return aggregation(query, getDefaultConfig(), filterConsumer, aggregation);
    }

    /**
     * 聚合查询
     *
     * @param query       查询条件
     * @param aggregation 聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(
            QUERY query,
            Function<Aggregation.Builder, ObjectBuilder<Aggregation>> aggregation
    ) {
        return aggregation(query, getDefaultConfig(), null, aggregation);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregation    聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(
            QUERY query,
            Consumer<BoolQuery.Builder> filterConsumer,
            Function<Aggregation.Builder, ObjectBuilder<Aggregation>> aggregation
    ) {
        return aggregation(query, getDefaultConfig(), filterConsumer, aggregation);
    }

    /**
     * 聚合查询
     *
     * @param query       查询条件
     * @param config      查询配置信息
     * @param aggregation 聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Function<Aggregation.Builder, ObjectBuilder<Aggregation>> aggregation
    ) {
        return aggregation(query, config, null, aggregation);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregation    聚合信息
     * @return 分页结果
     */
    Aggregate aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Consumer<BoolQuery.Builder> filterConsumer,
            Function<Aggregation.Builder, ObjectBuilder<Aggregation>> aggregation
    );

    /**
     * 聚合查询
     *
     * @param query       查询条件
     * @param config      查询配置信息
     * @param aggregation 聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Aggregation aggregation
    ) {
        var map = aggregation(query, config, null, Map.of(ElasticSearchCommonConstant.AGGREGATION_DEFAULT_NAME, aggregation));
        return map.get(ElasticSearchCommonConstant.AGGREGATION_DEFAULT_NAME);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregation    聚合信息
     * @return 分页结果
     */
    default Aggregate aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Consumer<BoolQuery.Builder> filterConsumer,
            Aggregation aggregation
    ) {
        var map = aggregation(query, config, filterConsumer, Map.of(ElasticSearchCommonConstant.AGGREGATION_DEFAULT_NAME, aggregation));
        return map.get(ElasticSearchCommonConstant.AGGREGATION_DEFAULT_NAME);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param aggregationMap 聚合信息
     * @return 分页结果
     */
    default Map<String, Aggregate> aggregation(
            QUERY query,
            Map<String, Aggregation> aggregationMap
    ) {
        return aggregation(query, getDefaultConfig(), null, aggregationMap);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregationMap 聚合信息
     * @return 分页结果
     */
    default Map<String, Aggregate> aggregation(
            QUERY query,
            Consumer<BoolQuery.Builder> filterConsumer,
            Map<String, Aggregation> aggregationMap
    ) {
        return aggregation(query, getDefaultConfig(), filterConsumer, aggregationMap);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param aggregationMap 聚合信息
     * @return 分页结果
     */
    default Map<String, Aggregate> aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Map<String, Aggregation> aggregationMap
    ) {
        return aggregation(query, config, null, aggregationMap);
    }

    /**
     * 聚合查询
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param filterConsumer 自定义的筛选条件内容
     * @param aggregationMap 聚合信息
     * @return 分页结果
     */
    Map<String, Aggregate> aggregation(
            QUERY query,
            ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config,
            Consumer<BoolQuery.Builder> filterConsumer,
            Map<String, Aggregation> aggregationMap
    );

    /**
     * 分页搜索
     *
     * @param query  查询条件
     * @param config 查询配置信息
     * @param cache  是否使用缓存
     * @return 分页结果
     */
    default PageModel<ELASTIC_VO> page(QUERY query, ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config, boolean cache) {
        if (cache) {
            var pageModel = getCache(query);
            if (pageModel != null) {
                return pageModel;
            }
            pageModel = page(query, config);
            setCache(query, pageModel);
            return pageModel;
        }
        return page(query, config);
    }

    /**
     * 获取第一条数据
     *
     * @param query  查询条件
     * @param config 查询配置信息
     * @return 数据信息
     */
    default ELASTIC_VO getFirst(QUERY query, ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config) {
        query.setPage(1);
        query.setRows(1);
        var pageModel = page(query, config);
        if (pageModel.getList().isEmpty()) {
            return null;
        }
        return pageModel.getList().getFirst();
    }

    /**
     * 查询数量信息
     *
     * @param query 查询条件
     * @return 数量信息
     */
    default long count(QUERY query) {
        return count(query, getDefaultConfig());
    }

    /**
     * 查询数量信息
     *
     * @param query          查询条件
     * @param filterConsumer 自定义的筛选条件内容
     * @return 数量信息
     */
    default long count(QUERY query, Consumer<BoolQuery.Builder> filterConsumer) {
        return count(query, getDefaultConfig(), filterConsumer);
    }

    /**
     * 查询数量信息
     * 参数构造参考https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html
     *
     * @param query  查询条件
     * @param config 查询配置信息
     * @return 数量信息
     */
    default long count(QUERY query, ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config) {
        return count(query, config, null);
    }

    /**
     * 查询数量信息
     * 参数构造参考https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html
     *
     * @param query          查询条件
     * @param config         查询配置信息
     * @param filterConsumer 自定义的筛选条件内容
     * @return 数量信息
     */
    long count(QUERY query, ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> config, Consumer<BoolQuery.Builder> filterConsumer);

    /**
     * 获取空的构造信息
     *
     * @return 空的构造信息
     */
    ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> getEmptyConfig();

    /**
     * 获取默认的构造信息
     *
     * @return 默认的构造信息
     */
    default ElasticSearchConfig<PO, ELASTIC_PO, ELASTIC_VO, QUERY> getDefaultConfig() {
        return getEmptyConfig();
    }

    /**
     * 设置缓存信息
     *
     * @param query     查询条件
     * @param pageModel 分页信息
     */
    default void setCache(QUERY query, PageModel<ELASTIC_VO> pageModel) {

    }

    /**
     * 获取缓存信息
     *
     * @param query 查询条件
     * @return 缓存信息
     */
    default PageModel<ELASTIC_VO> getCache(QUERY query) {
        return null;
    }

}
